//-----------------------------------------------------
// application.cpp
//-----------------------------------------------------

/**
 * comment here
 */

#include "application.h"
#include "applicationState.h"

#include <assert.h>

namespace application {

	CApplication* CApplication::_instance = 0;

	CApplication::CApplication() : _initialized(false), _termination(false),
			_currentState(0), _nextState(0)
	{
		assert(!_instance && "Only one instance of the application can be created");
		_instance = this;
	}

	bool CApplication::init() 
	{
		assert(!_initialized);
		_initialized = true;
		return true;
	}

	void CApplication::end()
	{
		_initialized = false;

		// Deactivate the current state
		if (_currentState)
			_currentState->onDeactivate();

		// Remove the states
		TStateTable::iterator it;

		// FIXME: end() changes if elements are removed?
		for (it = _states.begin(); it != _states.end(); ++it)
		{
			it->second->onDestroy();
			delete it->second;
		}
		_states.clear();

	}

	void CApplication::run()
	{
		// Execute the main loop
		while (!terminationRequested())
		{
			if ( !_currentState || (_nextState && (_currentState != _nextState)) )
				changeState();
			step();
		}
	}

	void CApplication::step()
	{
		if (_currentState)
			_currentState->onRun();
	}

	/**********************************************************/
	/*                   STATE FUNCTIONS                      */
	/**********************************************************/

	void CApplication::addState(const std::string &name, CApplicationState *newState)
	{
		TStateTable::const_iterator it;

#ifdef _DEBUG

		// Check that there isn't already a state with that name
		it = _states.find(name);
		assert(it == _states.end());

#endif

		// Add the state
		_states[name] = newState;
		newState->onCreate();
	}

	bool CApplication::setState(const std::string &name)
	{
		TStateTable::const_iterator it;

		// Search the state
		it = _states.find(name);

		// If there isn't a state with that name do nothing
		if (it == _states.end())
			return false;

		// Else set the state as the next state
		_nextState = it->second;

		return true;
	}

	void CApplication::changeState()
	{
		if (_currentState)
			_currentState->onDeactivate();
		assert(_nextState);
		_nextState->onActivate();
		_currentState = _nextState;
	}

} // namespace application
